歡迎來到第 15 天,今天要來說說代理 IP 池的概念。畢竟爬蟲的目的是完全自動化,如果要像昨天那樣人為的查找可使用 IP 有違爬蟲初衷。在做大量爬蟲的時候,通常需要多個 IP 彼此間切換以避免反爬蟲程式阻擋,而這時候可以簡單的花錢了事上網買代理 IP,這種產品的架構通常是給你一個 API 位置,傳送一個請求過去後面會有一個篩選邏輯幫我們處理掉尋找代理 IP 的工作,最後完成目標請求再回傳。那如果我們是要創建一個免費的代理 IP 池呢?
昨天推薦的兩個免費代理 IP 網站,送了一個請求過去,會發現所有的免費 IP 都被存在 <textarea>
裡,因此只要針對 <textarea>
當中的內容進行拆解,就可以取得所有的代理 IP。
import re
import requests
from lxml import etree
response = requests.get("https://free-proxy-list.net/")
html = etree.HTML(response.text)
list_ = html.xpath("//textarea")[0].text.split("\n")
ip_list = [ip for ip in list_ if re.match(r"\d*.\d*.\d*.\d*:\d*",ip)]
由於不是每個免費的代理 IP 都是可以使用的,因次在調用代理 IP 前需要測試是否可用,我們可以透過在調用前串接昨天的 https://api.ipify.org?format=json 進行驗證。依照爬蟲的規模,會另外撰寫驗證流成,但在小規模的狀況下,可以在調用代理 IP 時在做驗證,不需要在一開始就驗證完全部的代理 IP。(但此處為了做示範,將會驗證完全部的代理 IP,作為最終的目的)
import re
import requests
from lxml import etree
def get_proxy_ips():
response = requests.get("https://free-proxy-list.net/")
html = etree.HTML(response.text)
list_ = html.xpath("//textarea")[0].text.split("\n")
ip_list = [ip for ip in list_ if re.match(r"\d*.\d*.\d*.\d*:\d*",ip)]
def proxy_ip_validation(ip):
try:
if requests.get("https://api.ipify.org?format=json",proxies={"https":f"http://{ip}"}).text == ip.split(":")[0]:
return True
else:
return False
except:
return False
proxy_ips = get_proxy_ips()
validated_ips = []
for ip in proxy_ips:
if proxy_ip_validation(ip):
validated_ips.append(ip)
# validated_ips 為最終驗證完後可用的全部代理 IP
在完成這兩個功能後,可以結合爬蟲進行不同的邏輯組合,順利繼續執行爬蟲,閃避反爬蟲程式的封鎖。
今天就到這裡,明天見!